DESeq2 analysis of peak universe (joint peak set called in any
condition, must be called in all three replicates, MACS3)
bw_dir <- "/Volumes/DATA/DATA/Puck/bigwig/"
chromhmm <- "../genome/ESC_10_segments.mm39.bed"
library("wigglescout")
library("ggpubr")
library("ggplot2")
library("DESeq2")
library("dplyr")
library("ggrastr")
clean <- function (fn) {
fn <- gsub(pattern = ".+/", "", x = fn)
fn <- gsub(pattern = ".mm9.+", "", x = fn)
fn <- gsub(pattern = ".mm39.+", "", x = fn)
fn <- gsub(pattern = "_S.+", "", x = fn)
fn <- gsub(pattern = ".scaled.bw", "", x = fn)
fn <- gsub(pattern = ".unscaled.bw", "", x = fn)
fn <- gsub(pattern = "_batch2", "", x = fn)
fn <- gsub(pattern = "-", " ", x = fn)
fn <- gsub(pattern = "_", " ", x = fn)
fn <- gsub(pattern = " HA ", " ", x = fn)
fn <- gsub(pattern = "D1D6", "FANCJ-/-", x = fn)
fn <- gsub(pattern = "P2D2", "DHX36-/-", x = fn)
fn <- gsub(pattern = "P3D4", "FANCJ-/-DHX36-/-", x = fn)
return(fn)
}
BWs <- paste0(bw_dir,list.files(bw_dir,pattern="G4_.+R.\\.bw"))
mypal <-c("cornflowerblue","orange","red2","#505050")
mypal3 <-c("cornflowerblue","cornflowerblue","cornflowerblue","orange","orange","orange","red2","red2","red2","505050","505050","505050")
bw_granges_diff_analysis <- function(granges_c1,
granges_c2,
label_c1,
label_c2,
estimate_size_factors = FALSE,
as_granges = FALSE) {
# Bind first, get numbers after
names_values <- NULL
fields <- names(mcols(granges_c1))
if ("name" %in% fields) {
names_values <- mcols(granges_c1)[["name"]]
granges_c1 <- granges_c1[, fields[fields != "name"]]
}
fields <- names(mcols(granges_c2))
if ("name" %in% fields) {
granges_c2 <- granges_c2[, fields[fields != "name"]]
}
cts_df <- cbind(data.frame(granges_c1), mcols(granges_c2))
if (! is.null(names_values)) {
rownames(cts_df) <- names_values
}
# Needs to drop non-complete cases and match rows
complete <- complete.cases(cts_df)
cts_df <- cts_df[complete, ]
values_df <- cts_df[, 6:ncol(cts_df)] %>% dplyr::select(where(is.numeric))
cts <- get_nreads_columns(values_df)
condition_labels <- c(rep(label_c1, length(mcols(granges_c1))),
rep(label_c2, length(mcols(granges_c2))))
coldata <- data.frame(colnames(cts), condition = as.factor(condition_labels))
dds <- DESeq2::DESeqDataSetFromMatrix(countData = cts,
colData = coldata,
design = ~ condition,
rowRanges = granges_c1[complete, ])
if (estimate_size_factors == TRUE) {
dds <- DESeq2::estimateSizeFactors(dds)
}
else {
# Since files are scaled, we do not want to estimate size factors
sizeFactors(dds) <- c(rep(1, ncol(cts)))
}
dds <- DESeq2::estimateDispersions(dds)
dds <- DESeq2::nbinomWaldTest(dds)
if (as_granges) {
result <- DESeq2::results(dds, format = "GRanges",alpha = 0.01)
if (!is.null(names_values)) {
result$name <- names_values[complete]
}
}
else {
# result <- results(dds, format="DataFrame")
result <- dds
}
result
}
get_nreads_columns <- function(df, length_factor = 100) {
# Convert mean coverages to round integer read numbers
cts <- as.matrix(df)
cts <- as.matrix(cts[complete.cases(cts),])
cts <- round(cts*length_factor)
cts
}
peak_universe <- "../peaks/G4_combined_min3rep.bed"
BWs.WT <- BWs[grep("WT",BWs)]
BWs.FANCJ <- BWs[grep("D1D6",BWs)]
BWs.DHX36 <- BWs[grep("P2D2",BWs)]
BWs.DKO <- BWs[grep("P3D4",BWs)]
# Calculate here some loci or bins
cov.WT <- bw_loci(BWs.WT, loci = peak_universe)
cov.DHX36 <- bw_loci(BWs.DHX36, loci = peak_universe)
cov.FANCJ <- bw_loci(BWs.FANCJ, loci = peak_universe)
cov.DKO <- bw_loci(BWs.DKO, loci = peak_universe)
cov.WT$name <- paste0("peak_",1:length(cov.WT))
cov.DHX36$name <- paste0("peak_",1:length(cov.DHX36))
cov.FANCJ$name <- paste0("peak_",1:length(cov.FANCJ))
cov.DKO$name <- paste0("peak_",1:length(cov.DKO))
diff_DHX36 <- bw_granges_diff_analysis(cov.WT, cov.DHX36,
"WT", "DHX36KO")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
diff_FANCJ <- bw_granges_diff_analysis(cov.WT, cov.FANCJ,
"WT", "FANCJ")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
diff_DKO <- bw_granges_diff_analysis(cov.WT, cov.DKO,
"WT", "DKO")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
-- note: fitType='parametric', but the dispersion trend was not well captured by the
function: y = a/x + b, and a local regression fit was automatically substituted.
specify fitType='local' or 'mean' to avoid this message next time.
final dispersion estimates
# This takes care of low conts and things like this, but you can also use
# diff_results as is for the things below
lfc_DHX36 <- DESeq2::lfcShrink(diff_DHX36, coef = "condition_WT_vs_DHX36KO", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
lfc_FANCJ <- DESeq2::lfcShrink(diff_FANCJ, coef = "condition_WT_vs_FANCJ", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
lfc_DKO <- DESeq2::lfcShrink(diff_DKO, coef = "condition_WT_vs_DKO", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
data_DHX36 <- plotMA(lfc_DHX36, returnData = T)
data_DHX36$lfc <- -data_DHX36$lfc
data_DHX36$mean <- log10(data_DHX36$mean)
data_FANCJ <- plotMA(lfc_FANCJ, returnData = T)
data_FANCJ$lfc <- -data_FANCJ$lfc
data_FANCJ$mean <- log10(data_FANCJ$mean)
data_DKO <- plotMA(lfc_DKO, returnData = T)
data_DKO$lfc <- -data_DKO$lfc
data_DKO$mean <- log10(data_DKO$mean)
ggscatter(data_DHX36,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))

plot_MA_DHX36 <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_FANCJ,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[2])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))

plot_MA_FANCJ <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_DKO,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))

plot_MA_DKO <- rasterize(last_plot(), layers='Point', dpi=600)
data_DKO$lfc_DHX36 <- data_DHX36$lfc
data_DKO$lfc_FANCJ <- data_FANCJ$lfc
ggscatter(data_DKO,x ="lfc_DHX36",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

plot_LFC_DKO_vs_DHX36 <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_DKO,x ="lfc_FANCJ",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

plot_LFC_DKO_vs_FANCJ <- rasterize(last_plot(), layers='Point', dpi=600)
data_DHX36$lfc_DKO <- data_DKO$lfc
ggscatter(data_DHX36,x ="lfc",y="lfc_DKO",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

bed <- as.data.frame(cov.DHX36)[,1:3]
results_table <- data.frame(chr=bed$seqnames,start=bed$start,end=bed$end,name=cov.WT$name, baseMean=lfc_DKO$baseMean,DHX36=data_DHX36$isDE,FANCJ=data_FANCJ$isDE,DKO=data_DKO$isDE,DHX36lfc=data_DHX36$lfc,FANCJlfc=data_FANCJ$lfc,DKOlfc=data_DKO$lfc,dir=".")
results_table$nonsig <- !(results_table$DHX36 | results_table$FANCJ | results_table$DKO)
results_table$sig <- factor("lowlfc", levels=c("nonsig","lowlfc","FANCJ","DHX36","DKO"))
results_table$sig[(results_table$nonsig)] <- "nonsig"
results_table$sig[(results_table$DKO & results_table$DKOlfc>1)] <- "DKO"
results_table$sig[(results_table$DHX36 & results_table$DHX36lfc>1)] <- "DHX36"
results_table$sig[(results_table$FANCJ & results_table$FANCJlfc>1)] <- "FANCJ"
write.table(results_table,"G4_CnT_combined_peaks_DESeq_results.txt", row.names = F, col.names = T,quote = F, sep = "\t")
results_table$sig <- factor(levels=c("nonsig","lowlfc","FANCJ","DHX36","DKO"))
Error in `$<-.data.frame`(`*tmp*`, sig, value = integer(0)) :
replacement has 0 rows, data has 71445
library(eulerr)
v <- list(DHX36=DHX36_bed$name,FANCJ=FANCJ_bed$name,DKO=DKO_bed$name)
plot_Venn_all <- plot(euler(v),quantities=T, border="black")
plot_Venn_all

library(eulerr)
DKOneg <- results_table[(results_table$DKO==TRUE & results_table$DKOlfc< -1),c(4)]
v <- list(all=cov.WT$name,DKOneg=DKOneg,DKO=DKO_bed$name)
plot_Venn_DKO <- plot(euler(v),quantities=T)
plot_Venn_DKO

dir.create("./plots",showWarnings = F)
ggsave("plots/peaks_DESeq2_MA_DHX36.pdf",plot_MA_DHX36,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_MA_FANCJ.pdf",plot_MA_FANCJ,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_MA_DKO.pdf",plot_MA_DKO,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_LFC_DHX36.pdf",plot_LFC_DKO_vs_DHX36,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_LFC_FANCJ.pdf",plot_LFC_DKO_vs_FANCJ,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_Venn_KOs.pdf",plot_Venn_all,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_Venn_DKO_vs_all.pdf",plot_Venn_DKO,width = 4, height= 4)
library(cowplot)
dir.create("./panels",showWarnings = F)
library("cowplot")
p <- ggdraw() +
draw_plot(plot_MA_DHX36, x = 0, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_FANCJ, x = .33, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_DKO, x = 0.66, y = 0.5, width = .33, height = 0.5) +
draw_plot(plot_LFC_DKO_vs_DHX36, x = 0, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_LFC_DKO_vs_FANCJ, x = 0.33, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_Venn_all, x = 0.66, y = 0, width = 0.33, height = 0.5) +
draw_plot_label(label = c("a", "b", "c","d","e","f"), size = 15,
x = c(0, 0.33, 0.66, 0, 0.33, 0.66), y = c(1, 1, 1, 0.5, 0.5, 0.5))
p

ggsave("panels/peaks_DESeq2.pdf",p,width=10, height=6)
library(reshape2)
mdf <- melt(data.frame(name=rownames(cov),cov[,6:21]))
Using name, DHX36_sig, FANCJ_sig, DKO_sig, non_sig as id variables
mdf <- mdf[mdf$value<500,]
mdf$cond <- "WT"
mdf$cond[grep("DHX",mdf$variable)] <- "DHX36-/-"
mdf$cond[grep("FAN",mdf$variable)] <- "FANCJ-/-"
mdf$cond[grep("DKO",mdf$variable)] <- "DHX36-/-FANCJ-/-"
plot_viol_rep_all_peaks <- ggviolin(mdf, x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,30))
plot_viol_rep_all_peaks

plot_viol_rep_DHX36_peaks <- ggviolin(mdf[mdf$DHX36_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,30))
plot_viol_rep_DHX36_peaks

ggviolin(mdf[mdf$FANCJ_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,30))

plot_viol_rep_DKO_peaks <- ggviolin(mdf[mdf$DKO_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,30))
plot_viol_rep_DKO_peaks

plot_viol_rep_nonsig_peaks <- ggviolin(mdf[mdf$non_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,30))
plot_viol_rep_nonsig_peaks

ggsave("plots/peaks_DESeq2_viol_rep_all.pdf",plot_viol_rep_all_peaks,width = 2, height= 3)
ggsave("plots/peaks_DESeq2_viol_rep_DKO.pdf",plot_viol_rep_DKO_peaks,width = 2, height= 3)
ggsave("plots/peaks_DESeq2_viol_rep_DHX36.pdf",plot_viol_rep_DHX36_peaks,width = 2, height= 3)
ggsave("plots/peaks_DESeq2_viol_rep_nonsig.pdf",plot_viol_rep_nonsig_peaks,width = 2, height= 3)
sdf <- aggregate(value ~ name + cond, data=mdf, FUN="mean")
sdf$cond <- factor(sdf$cond,levels=c("WT","DHX36-/-","FANCJ-/-","DHX36-/-FANCJ-/-"))
ggviolin(sdf, x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,50))

sdf$DHX36_sig <- sdf$name %in% DHX36_bed$name
sdf$FANCJ_sig <- sdf$name %in% FANCJ_bed$name
sdf$DKO_sig <- sdf$name %in% DKO_bed$name
sdf$DKO_top <- sdf$name %in% DKO_bed_top$name
ggviolin(sdf[sdf$DHX36,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

ggviolin(sdf[sdf$FANCJ_sig,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

ggviolin(sdf[sdf$DKO_sig,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

ggviolin(sdf[sdf$DKO_top,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

LS0tCnRpdGxlOiAiRzQgQ1VUJlRhZyBhbmFseXNpcyBtRVNDIChXVCwgRkFOQ0ogS08sIERIWDM2IEtPLCBES08pIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpTaW1vbiBFbHPDpHNzZXIsIEthcm9saW5za2EgSW5zdGl0dXRldCAoMjAyMykKCiMjIyBERVNlcTIgYW5hbHlzaXMgb2YgcGVhayB1bml2ZXJzZSAoam9pbnQgcGVhayBzZXQgY2FsbGVkIGluIGFueSBjb25kaXRpb24sIG11c3QgYmUgY2FsbGVkIGluIGFsbCB0aHJlZSByZXBsaWNhdGVzLCBNQUNTMykKCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0zfQpid19kaXIgPC0gIi9Wb2x1bWVzL0RBVEEvREFUQS9QdWNrL2JpZ3dpZy8iCmNocm9taG1tIDwtICIuLi9nZW5vbWUvRVNDXzEwX3NlZ21lbnRzLm1tMzkuYmVkIgoKbGlicmFyeSgid2lnZ2xlc2NvdXQiKQpsaWJyYXJ5KCJnZ3B1YnIiKQpsaWJyYXJ5KCJnZ3Bsb3QyIikKbGlicmFyeSgiREVTZXEyIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJnZ3Jhc3RyIikKCmNsZWFuIDwtIGZ1bmN0aW9uIChmbikgewogIGZuIDwtIGdzdWIocGF0dGVybiA9ICIuKy8iLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICIubW05LisiLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICIubW0zOS4rIiwgIiIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiX1MuKyIsICIiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIi5zY2FsZWQuYnciLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICIudW5zY2FsZWQuYnciLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJfYmF0Y2gyIiwgIiIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiLSIsICIgIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJfIiwgIiAiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIiBIQSAiLCAiICIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiRDFENiIsICJGQU5DSi0vLSIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiUDJEMiIsICJESFgzNi0vLSIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiUDNENCIsICJGQU5DSi0vLURIWDM2LS8tIiwgeCA9IGZuKQogIHJldHVybihmbikKfQoKQldzIDwtIHBhc3RlMChid19kaXIsbGlzdC5maWxlcyhid19kaXIscGF0dGVybj0iRzRfLitSLlxcLmJ3IikpCgpteXBhbCA8LWMoImNvcm5mbG93ZXJibHVlIiwib3JhbmdlIiwicmVkMiIsIiM1MDUwNTAiKQpteXBhbDMgPC1jKCJjb3JuZmxvd2VyYmx1ZSIsImNvcm5mbG93ZXJibHVlIiwiY29ybmZsb3dlcmJsdWUiLCJvcmFuZ2UiLCJvcmFuZ2UiLCJvcmFuZ2UiLCJyZWQyIiwicmVkMiIsInJlZDIiLCI1MDUwNTAiLCI1MDUwNTAiLCI1MDUwNTAiKQpgYGAKCmBgYHtyfQpid19ncmFuZ2VzX2RpZmZfYW5hbHlzaXMgPC0gZnVuY3Rpb24oZ3Jhbmdlc19jMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYW5nZXNfYzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbF9jMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX2MyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdGVfc2l6ZV9mYWN0b3JzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc19ncmFuZ2VzID0gRkFMU0UpIHsKCiAgIyBCaW5kIGZpcnN0LCBnZXQgbnVtYmVycyBhZnRlcgogIG5hbWVzX3ZhbHVlcyA8LSBOVUxMCiAgZmllbGRzIDwtIG5hbWVzKG1jb2xzKGdyYW5nZXNfYzEpKQoKICBpZiAoIm5hbWUiICVpbiUgZmllbGRzKSB7CiAgICBuYW1lc192YWx1ZXMgPC0gbWNvbHMoZ3Jhbmdlc19jMSlbWyJuYW1lIl1dCiAgICBncmFuZ2VzX2MxIDwtIGdyYW5nZXNfYzFbLCBmaWVsZHNbZmllbGRzICE9ICJuYW1lIl1dCiAgfQoKICBmaWVsZHMgPC0gbmFtZXMobWNvbHMoZ3Jhbmdlc19jMikpCiAgaWYgKCJuYW1lIiAlaW4lIGZpZWxkcykgewogICAgZ3Jhbmdlc19jMiA8LSBncmFuZ2VzX2MyWywgZmllbGRzW2ZpZWxkcyAhPSAibmFtZSJdXQogIH0KCiAgY3RzX2RmIDwtIGNiaW5kKGRhdGEuZnJhbWUoZ3Jhbmdlc19jMSksIG1jb2xzKGdyYW5nZXNfYzIpKQoKICBpZiAoISBpcy5udWxsKG5hbWVzX3ZhbHVlcykpIHsKICAgIHJvd25hbWVzKGN0c19kZikgPC0gbmFtZXNfdmFsdWVzCiAgfQoKICAjIE5lZWRzIHRvIGRyb3Agbm9uLWNvbXBsZXRlIGNhc2VzIGFuZCBtYXRjaCByb3dzCiAgY29tcGxldGUgPC0gY29tcGxldGUuY2FzZXMoY3RzX2RmKQogIGN0c19kZiA8LSBjdHNfZGZbY29tcGxldGUsIF0KCiAgdmFsdWVzX2RmIDwtIGN0c19kZlssIDY6bmNvbChjdHNfZGYpXSAlPiUgZHBseXI6OnNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkKICBjdHMgPC0gZ2V0X25yZWFkc19jb2x1bW5zKHZhbHVlc19kZikKCiAgY29uZGl0aW9uX2xhYmVscyA8LSBjKHJlcChsYWJlbF9jMSwgbGVuZ3RoKG1jb2xzKGdyYW5nZXNfYzEpKSksCiAgICAgICAgICAgICAgICAgICAgICAgIHJlcChsYWJlbF9jMiwgbGVuZ3RoKG1jb2xzKGdyYW5nZXNfYzIpKSkpCgoKICBjb2xkYXRhIDwtIGRhdGEuZnJhbWUoY29sbmFtZXMoY3RzKSwgY29uZGl0aW9uID0gYXMuZmFjdG9yKGNvbmRpdGlvbl9sYWJlbHMpKQoKICBkZHMgPC0gREVTZXEyOjpERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGN0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gY29sZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IGNvbmRpdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3dSYW5nZXMgPSBncmFuZ2VzX2MxW2NvbXBsZXRlLCBdKQoKCiAgaWYgKGVzdGltYXRlX3NpemVfZmFjdG9ycyA9PSBUUlVFKSB7CiAgICBkZHMgPC0gREVTZXEyOjplc3RpbWF0ZVNpemVGYWN0b3JzKGRkcykKICB9CiAgZWxzZSB7CiAgICAjIFNpbmNlIGZpbGVzIGFyZSBzY2FsZWQsIHdlIGRvIG5vdCB3YW50IHRvIGVzdGltYXRlIHNpemUgZmFjdG9ycwogICAgc2l6ZUZhY3RvcnMoZGRzKSA8LSBjKHJlcCgxLCBuY29sKGN0cykpKQogIH0KCiAgZGRzIDwtIERFU2VxMjo6ZXN0aW1hdGVEaXNwZXJzaW9ucyhkZHMpCiAgZGRzIDwtIERFU2VxMjo6bmJpbm9tV2FsZFRlc3QoZGRzKQoKICBpZiAoYXNfZ3JhbmdlcykgewogICAgcmVzdWx0IDwtIERFU2VxMjo6cmVzdWx0cyhkZHMsIGZvcm1hdCA9ICJHUmFuZ2VzIixhbHBoYSA9IDAuMDEpCiAgICBpZiAoIWlzLm51bGwobmFtZXNfdmFsdWVzKSkgewogICAgICByZXN1bHQkbmFtZSA8LSBuYW1lc192YWx1ZXNbY29tcGxldGVdCiAgICB9CgogIH0KICBlbHNlIHsKICAgICMgcmVzdWx0IDwtIHJlc3VsdHMoZGRzLCBmb3JtYXQ9IkRhdGFGcmFtZSIpCiAgICByZXN1bHQgPC0gZGRzCiAgfQoKICByZXN1bHQKfQoKZ2V0X25yZWFkc19jb2x1bW5zIDwtIGZ1bmN0aW9uKGRmLCBsZW5ndGhfZmFjdG9yID0gMTAwKSB7CiAgIyBDb252ZXJ0IG1lYW4gY292ZXJhZ2VzIHRvIHJvdW5kIGludGVnZXIgcmVhZCBudW1iZXJzCiAgY3RzIDwtIGFzLm1hdHJpeChkZikKICBjdHMgPC0gYXMubWF0cml4KGN0c1tjb21wbGV0ZS5jYXNlcyhjdHMpLF0pCiAgY3RzIDwtIHJvdW5kKGN0cypsZW5ndGhfZmFjdG9yKQogIGN0cwp9CmBgYAoKYGBge3J9CgpwZWFrX3VuaXZlcnNlIDwtICIuLi9wZWFrcy9HNF9jb21iaW5lZF9taW4zcmVwLmJlZCIKCkJXcy5XVCA8LSBCV3NbZ3JlcCgiV1QiLEJXcyldCkJXcy5GQU5DSiA8LSBCV3NbZ3JlcCgiRDFENiIsQldzKV0KQldzLkRIWDM2IDwtIEJXc1tncmVwKCJQMkQyIixCV3MpXQpCV3MuREtPIDwtIEJXc1tncmVwKCJQM0Q0IixCV3MpXQogIAojIENhbGN1bGF0ZSBoZXJlIHNvbWUgbG9jaSBvciBiaW5zCmNvdi5XVCA8LSBid19sb2NpKEJXcy5XVCwgbG9jaSA9IHBlYWtfdW5pdmVyc2UpCmNvdi5ESFgzNiA8LSBid19sb2NpKEJXcy5ESFgzNiwgbG9jaSA9IHBlYWtfdW5pdmVyc2UpCmNvdi5GQU5DSiA8LSBid19sb2NpKEJXcy5GQU5DSiwgbG9jaSA9IHBlYWtfdW5pdmVyc2UpCmNvdi5ES08gPC0gYndfbG9jaShCV3MuREtPLCBsb2NpID0gcGVha191bml2ZXJzZSkKCmNvdi5XVCRuYW1lIDwtIHBhc3RlMCgicGVha18iLDE6bGVuZ3RoKGNvdi5XVCkpCmNvdi5ESFgzNiRuYW1lIDwtIHBhc3RlMCgicGVha18iLDE6bGVuZ3RoKGNvdi5ESFgzNikpCmNvdi5GQU5DSiRuYW1lIDwtIHBhc3RlMCgicGVha18iLDE6bGVuZ3RoKGNvdi5GQU5DSikpCmNvdi5ES08kbmFtZSA8LSBwYXN0ZTAoInBlYWtfIiwxOmxlbmd0aChjb3YuREtPKSkKYGBgCgpgYGB7cn0KZGlmZl9ESFgzNiA8LSBid19ncmFuZ2VzX2RpZmZfYW5hbHlzaXMoY292LldULCBjb3YuREhYMzYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV1QiLCAiREhYMzZLTyIpCmRpZmZfRkFOQ0ogPC0gYndfZ3Jhbmdlc19kaWZmX2FuYWx5c2lzKGNvdi5XVCwgY292LkZBTkNKLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldUIiwgIkZBTkNKIikKZGlmZl9ES08gPC0gYndfZ3Jhbmdlc19kaWZmX2FuYWx5c2lzKGNvdi5XVCwgY292LkRLTywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXVCIsICJES08iKQoKCiMgVGhpcyB0YWtlcyBjYXJlIG9mIGxvdyBjb250cyBhbmQgdGhpbmdzIGxpa2UgdGhpcywgYnV0IHlvdSBjYW4gYWxzbyB1c2UKIyBkaWZmX3Jlc3VsdHMgYXMgaXMgZm9yIHRoZSB0aGluZ3MgYmVsb3cKbGZjX0RIWDM2IDwtIERFU2VxMjo6bGZjU2hyaW5rKGRpZmZfREhYMzYsIGNvZWYgPSAiY29uZGl0aW9uX1dUX3ZzX0RIWDM2S08iLCB0eXBlPSJhcGVnbG0iKQpsZmNfRkFOQ0ogPC0gREVTZXEyOjpsZmNTaHJpbmsoZGlmZl9GQU5DSiwgY29lZiA9ICJjb25kaXRpb25fV1RfdnNfRkFOQ0oiLCB0eXBlPSJhcGVnbG0iKQpsZmNfREtPIDwtIERFU2VxMjo6bGZjU2hyaW5rKGRpZmZfREtPLCBjb2VmID0gImNvbmRpdGlvbl9XVF92c19ES08iLCB0eXBlPSJhcGVnbG0iKQoKZGF0YV9ESFgzNiA8LSBwbG90TUEobGZjX0RIWDM2LCByZXR1cm5EYXRhID0gVCkKZGF0YV9ESFgzNiRsZmMgPC0gLWRhdGFfREhYMzYkbGZjCmRhdGFfREhYMzYkbWVhbiA8LSBsb2cxMChkYXRhX0RIWDM2JG1lYW4pCgpkYXRhX0ZBTkNKIDwtIHBsb3RNQShsZmNfRkFOQ0osIHJldHVybkRhdGEgPSBUKQpkYXRhX0ZBTkNKJGxmYyA8LSAtZGF0YV9GQU5DSiRsZmMKZGF0YV9GQU5DSiRtZWFuIDwtIGxvZzEwKGRhdGFfRkFOQ0okbWVhbikKCmRhdGFfREtPIDwtIHBsb3RNQShsZmNfREtPLCByZXR1cm5EYXRhID0gVCkKZGF0YV9ES08kbGZjIDwtIC1kYXRhX0RLTyRsZmMKZGF0YV9ES08kbWVhbiA8LSBsb2cxMChkYXRhX0RLTyRtZWFuKQpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpnZ3NjYXR0ZXIoZGF0YV9ESFgzNix4ID0ibWVhbiIseT0ibGZjIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbMV0pKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpKQpwbG90X01BX0RIWDM2IDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApIApgYGAKCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9Cmdnc2NhdHRlcihkYXRhX0ZBTkNKLHggPSJtZWFuIix5PSJsZmMiLGNvbG9yPSJpc0RFIixzaXplID0gMC44LCBhbHBoYT0wLjUsIHBhbGV0dGUgPSBjKCJncmF5IixteXBhbFsyXSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTUsNSkpCnBsb3RfTUFfRkFOQ0ogPC0gcmFzdGVyaXplKGxhc3RfcGxvdCgpLCBsYXllcnM9J1BvaW50JywgZHBpPTYwMCkgCmBgYAoKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KZ2dzY2F0dGVyKGRhdGFfREtPLHggPSJtZWFuIix5PSJsZmMiLGNvbG9yPSJpc0RFIixzaXplID0gMC44LCBhbHBoYT0wLjUsIHBhbGV0dGUgPSBjKCJncmF5IixteXBhbFszXSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTUsNSkpCnBsb3RfTUFfREtPIDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApIApgYGAKCgpgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpkYXRhX0RLTyRsZmNfREhYMzYgPC0gZGF0YV9ESFgzNiRsZmMKZGF0YV9ES08kbGZjX0ZBTkNKIDwtIGRhdGFfRkFOQ0okbGZjCmdnc2NhdHRlcihkYXRhX0RLTyx4ID0ibGZjX0RIWDM2Iix5PSJsZmMiLGNvbG9yPSJpc0RFIixzaXplID0gMC44LCBhbHBoYT0wLjUsIHBhbGV0dGUgPSBjKCJncmF5IixteXBhbFszXSkpKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0wLjEpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTUsNSksIHhsaW09YygtNSw1KSkKcGxvdF9MRkNfREtPX3ZzX0RIWDM2IDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApCmBgYApgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpnZ3NjYXR0ZXIoZGF0YV9ES08seCA9ImxmY19GQU5DSiIseT0ibGZjIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbM10pKSsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpLCB4bGltPWMoLTUsNSkpCnBsb3RfTEZDX0RLT192c19GQU5DSiA8LSByYXN0ZXJpemUobGFzdF9wbG90KCksIGxheWVycz0nUG9pbnQnLCBkcGk9NjAwKQpgYGAKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KZGF0YV9ESFgzNiRsZmNfREtPIDwtIGRhdGFfREtPJGxmYwpnZ3NjYXR0ZXIoZGF0YV9ESFgzNix4ID0ibGZjIix5PSJsZmNfREtPIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbMV0pKSsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpLCB4bGltPWMoLTUsNSkpCmBgYAoKYGBge3J9CmJlZCA8LSBhcy5kYXRhLmZyYW1lKGNvdi5ESFgzNilbLDE6M10KCnJlc3VsdHNfdGFibGUgPC0gZGF0YS5mcmFtZShjaHI9YmVkJHNlcW5hbWVzLHN0YXJ0PWJlZCRzdGFydCxlbmQ9YmVkJGVuZCxuYW1lPWNvdi5XVCRuYW1lLCBiYXNlTWVhbj1sZmNfREtPJGJhc2VNZWFuLERIWDM2PWRhdGFfREhYMzYkaXNERSxGQU5DSj1kYXRhX0ZBTkNKJGlzREUsREtPPWRhdGFfREtPJGlzREUsREhYMzZsZmM9ZGF0YV9ESFgzNiRsZmMsRkFOQ0psZmM9ZGF0YV9GQU5DSiRsZmMsREtPbGZjPWRhdGFfREtPJGxmYyxkaXI9Ii4iKQoKcmVzdWx0c190YWJsZSRub25zaWcgPC0gIShyZXN1bHRzX3RhYmxlJERIWDM2IHwgcmVzdWx0c190YWJsZSRGQU5DSiB8IHJlc3VsdHNfdGFibGUkREtPKQoKcmVzdWx0c190YWJsZSRzaWcgPC0gZmFjdG9yKCJsb3dsZmMiLCBsZXZlbHM9Yygibm9uc2lnIiwibG93bGZjIiwiRkFOQ0oiLCJESFgzNiIsIkRLTyIpKQpyZXN1bHRzX3RhYmxlJHNpZ1socmVzdWx0c190YWJsZSRub25zaWcpXSA8LSAibm9uc2lnIgpyZXN1bHRzX3RhYmxlJHNpZ1socmVzdWx0c190YWJsZSRES08gJiByZXN1bHRzX3RhYmxlJERLT2xmYz4xKV0gPC0gIkRLTyIKcmVzdWx0c190YWJsZSRzaWdbKHJlc3VsdHNfdGFibGUkREhYMzYgJiByZXN1bHRzX3RhYmxlJERIWDM2bGZjPjEpXSA8LSAiREhYMzYiCnJlc3VsdHNfdGFibGUkc2lnWyhyZXN1bHRzX3RhYmxlJEZBTkNKICYgcmVzdWx0c190YWJsZSRGQU5DSmxmYz4xKV0gPC0gIkZBTkNKIgoKd3JpdGUudGFibGUocmVzdWx0c190YWJsZSwiRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX3Jlc3VsdHMudHh0Iiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gVCxxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCmBgYAoKYGBge3J9CkRIWDM2X2JlZCA8LSByZXN1bHRzX3RhYmxlWyhyZXN1bHRzX3RhYmxlJERIWDM2ICYgcmVzdWx0c190YWJsZSRESFgzNmxmYz4xKSxjKDEsMiwzLDQsOSwxMildCndyaXRlLnRhYmxlKERIWDM2X2JlZCwiLi4vcGVha3MvRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX0RIWDM2X3NpZy5iZWQiLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGLHF1b3RlID0gRiwgc2VwID0gIlx0IikKCkZBTkNKX2JlZCA8LSByZXN1bHRzX3RhYmxlWyhyZXN1bHRzX3RhYmxlJEZBTkNKICYgcmVzdWx0c190YWJsZSRGQU5DSmxmYz4xKSxjKDEsMiwzLDQsMTAsMTIpXQp3cml0ZS50YWJsZShGQU5DSl9iZWQsIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9GQU5DSl9zaWcuYmVkIiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRixxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCgpES09fYmVkIDwtIHJlc3VsdHNfdGFibGVbKHJlc3VsdHNfdGFibGUkREtPICYgcmVzdWx0c190YWJsZSRES09sZmM+MSksYygxLDIsMyw0LDExLDEyKV0Kd3JpdGUudGFibGUoREtPX2JlZCwiLi4vcGVha3MvRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX0RLT19zaWcuYmVkIiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRixxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCgpub25zaWdfYmVkIDwtIHJlc3VsdHNfdGFibGVbcmVzdWx0c190YWJsZSRub25zaWcgLGMoMSwyLDMsNCwxMSwxMildCndyaXRlLnRhYmxlKG5vbnNpZ19iZWQsIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9ub25zaWcuYmVkIiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRixxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCgpES09fYmVkX3RvcCA8LSByZXN1bHRzX3RhYmxlWyhyZXN1bHRzX3RhYmxlJERLTz09VFJVRSAmIHJlc3VsdHNfdGFibGUkREtPbGZjPjIgJiByZXN1bHRzX3RhYmxlJGJhc2VNZWFuID4gMTAwKSxjKDEsMiwzLDQsMTEsMTIpXQp3cml0ZS50YWJsZShES09fYmVkX3RvcCwiLi4vcGVha3MvRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX0RLT19zaWdfbGZjX2Jhc2VfY3V0b2ZmLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQoKCndyaXRlLnRhYmxlKGNiaW5kKHJlc3VsdHNfdGFibGVbLGMoMSwyLDMpXSxyZXN1bHRzX3RhYmxlJHNpZyxhcy5udW1lcmljKHJlc3VsdHNfdGFibGUkc2lnKSwiLiIpLCIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfc2lnX2NhdGVnb3JpZXMuYmVkIiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRixxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCmBgYAoKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KbGlicmFyeShldWxlcnIpCnYgPC0gbGlzdChESFgzNj1ESFgzNl9iZWQkbmFtZSxGQU5DSj1GQU5DSl9iZWQkbmFtZSxES089REtPX2JlZCRuYW1lKQpwbG90X1Zlbm5fYWxsIDwtIHBsb3QoZXVsZXIodikscXVhbnRpdGllcz1ULCBib3JkZXI9ImJsYWNrIikKcGxvdF9WZW5uX2FsbApgYGAKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KbGlicmFyeShldWxlcnIpCkRLT25lZyA8LSByZXN1bHRzX3RhYmxlWyhyZXN1bHRzX3RhYmxlJERLTz09VFJVRSAmIHJlc3VsdHNfdGFibGUkREtPbGZjPCAtMSksYyg0KV0KdiA8LSBsaXN0KGFsbD1jb3YuV1QkbmFtZSxES09uZWc9REtPbmVnLERLTz1ES09fYmVkJG5hbWUpCnBsb3RfVmVubl9ES08gPC0gcGxvdChldWxlcih2KSxxdWFudGl0aWVzPVQpCnBsb3RfVmVubl9ES08KYGBgCmBgYHtyfQpkaXIuY3JlYXRlKCIuL3Bsb3RzIixzaG93V2FybmluZ3MgPSBGKQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl9NQV9ESFgzNi5wZGYiLHBsb3RfTUFfREhYMzYsd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX01BX0ZBTkNKLnBkZiIscGxvdF9NQV9GQU5DSix3aWR0aCA9IDQsIGhlaWdodD0gNCkKZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfTUFfREtPLnBkZiIscGxvdF9NQV9ES08sd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX0xGQ19ESFgzNi5wZGYiLHBsb3RfTEZDX0RLT192c19ESFgzNix3aWR0aCA9IDQsIGhlaWdodD0gNCkKZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfTEZDX0ZBTkNKLnBkZiIscGxvdF9MRkNfREtPX3ZzX0ZBTkNKLHdpZHRoID0gNCwgaGVpZ2h0PSA0KQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl9WZW5uX0tPcy5wZGYiLHBsb3RfVmVubl9hbGwsd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX1Zlbm5fREtPX3ZzX2FsbC5wZGYiLHBsb3RfVmVubl9ES08sd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmBgYCAKCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9CmxpYnJhcnkoY293cGxvdCkKZGlyLmNyZWF0ZSgiLi9wYW5lbHMiLHNob3dXYXJuaW5ncyA9IEYpCgpsaWJyYXJ5KCJjb3dwbG90IikKcCA8LSBnZ2RyYXcoKSArCiAgZHJhd19wbG90KHBsb3RfTUFfREhYMzYsIHggPSAwLCB5ID0gMC41LCB3aWR0aCA9IC4zMywgaGVpZ2h0ID0gLjUpICsKICBkcmF3X3Bsb3QocGxvdF9NQV9GQU5DSiwgeCA9IC4zMywgeSA9IDAuNSwgd2lkdGggPSAuMzMsIGhlaWdodCA9IC41KSArCiAgZHJhd19wbG90KHBsb3RfTUFfREtPLCB4ID0gMC42NiwgeSA9IDAuNSwgd2lkdGggPSAuMzMsIGhlaWdodCA9IDAuNSkgKwogIGRyYXdfcGxvdChwbG90X0xGQ19ES09fdnNfREhYMzYsIHggPSAwLCB5ID0gMCwgd2lkdGggPSAwLjMzLCBoZWlnaHQgPSAwLjUpICsKICBkcmF3X3Bsb3QocGxvdF9MRkNfREtPX3ZzX0ZBTkNKLCB4ID0gMC4zMywgeSA9IDAsIHdpZHRoID0gMC4zMywgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90KHBsb3RfVmVubl9hbGwsIHggPSAwLjY2LCB5ID0gMCwgd2lkdGggPSAwLjMzLCBoZWlnaHQgPSAwLjUpICsKICBkcmF3X3Bsb3RfbGFiZWwobGFiZWwgPSBjKCJhIiwgImIiLCAiYyIsImQiLCJlIiwiZiIpLCBzaXplID0gMTUsCiAgICAgICAgICAgICAgICAgIHggPSBjKDAsIDAuMzMsIDAuNjYsIDAsIDAuMzMsIDAuNjYpLCB5ID0gYygxLCAxLCAxLCAwLjUsIDAuNSwgMC41KSkKcApnZ3NhdmUoInBhbmVscy9wZWFrc19ERVNlcTIucGRmIixwLHdpZHRoPTEwLCBoZWlnaHQ9NikKYGBgIAoKYGBge3J9CmNvdiA8LSBjYmluZCggYXMuZGF0YS5mcmFtZShjb3YuV1QpWywxOjhdLCAKICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKGNvdi5ESFgzNilbLDY6OF0sIAogICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUoY292LkZBTkNKKVssNjo4XSwgCiAgICAgICAgICAgICAgYXMuZGF0YS5mcmFtZShjb3YuREtPKVssNjo4XSkKCmNvbG5hbWVzKGNvdikgPC0gYyhjb2xuYW1lcyhjb3YpWzE6NV0sIldUMSIsIldUMiIsIldUMyIsIkRIWDEiLCJESFgyIiwiREhYMyIsIkZBTjEiLCJGQU4yIiwiRkFOMyIsIkRLTzEiLCJES08yIiwiREtPMyIpCgpyb3duYW1lcyhjb3YpIDwtIGFzLmRhdGEuZnJhbWUoY292LldUKSRuYW1lCgpjb3YkREhYMzZfc2lnIDwtIHJvd25hbWVzKGNvdikgJWluJSBESFgzNl9iZWQkbmFtZQpjb3YkRkFOQ0pfc2lnIDwtIHJvd25hbWVzKGNvdikgJWluJSBGQU5DSl9iZWQkbmFtZQpjb3YkREtPX3NpZyA8LSByb3duYW1lcyhjb3YpICVpbiUgREtPX2JlZCRuYW1lCmNvdiRub25fc2lnIDwtIHdpdGgoY292LCAhKERIWDM2X3NpZyB8IEZBTkNKX3NpZyB8IERLT19zaWcpKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CmxpYnJhcnkocmVzaGFwZTIpCm1kZiA8LSBtZWx0KGRhdGEuZnJhbWUobmFtZT1yb3duYW1lcyhjb3YpLGNvdlssNjoyMV0pKQptZGYgPC0gbWRmW21kZiR2YWx1ZTw1MDAsXQptZGYkY29uZCA8LSAiV1QiCm1kZiRjb25kW2dyZXAoIkRIWCIsbWRmJHZhcmlhYmxlKV0gPC0gIkRIWDM2LS8tIgptZGYkY29uZFtncmVwKCJGQU4iLG1kZiR2YXJpYWJsZSldIDwtICJGQU5DSi0vLSIKbWRmJGNvbmRbZ3JlcCgiREtPIixtZGYkdmFyaWFibGUpXSA8LSAiREhYMzYtLy1GQU5DSi0vLSIKcGxvdF92aW9sX3JlcF9hbGxfcGVha3MgPC0gZ2d2aW9saW4obWRmLCB4PSJ2YXJpYWJsZSIseT0idmFsdWUiLGZpbGw9ImNvbmQiLHBhbGV0dGUgPSBteXBhbCwgYWRkPSJtZWFuX3NkIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwzMCkpCnBsb3RfdmlvbF9yZXBfYWxsX3BlYWtzCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30KcGxvdF92aW9sX3JlcF9ESFgzNl9wZWFrcyA8LSBnZ3Zpb2xpbihtZGZbbWRmJERIWDM2X3NpZyxdLCB4PSJ2YXJpYWJsZSIseT0idmFsdWUiLGZpbGw9ImNvbmQiLHBhbGV0dGUgPSBteXBhbCwgYWRkPSJtZWFuX3NkIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwzMCkpCnBsb3RfdmlvbF9yZXBfREhYMzZfcGVha3MKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpnZ3Zpb2xpbihtZGZbbWRmJEZBTkNKX3NpZyxdLCB4PSJ2YXJpYWJsZSIseT0idmFsdWUiLGZpbGw9ImNvbmQiLHBhbGV0dGUgPSBteXBhbCwgYWRkPSJtZWFuX3NkIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwzMCkpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30KcGxvdF92aW9sX3JlcF9ES09fcGVha3MgPC0gZ2d2aW9saW4obWRmW21kZiRES09fc2lnLF0sIHg9InZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDMwKSkKcGxvdF92aW9sX3JlcF9ES09fcGVha3MKYGBgCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CnBsb3RfdmlvbF9yZXBfbm9uc2lnX3BlYWtzIDwtIGdndmlvbGluKG1kZlttZGYkbm9uX3NpZyxdLCB4PSJ2YXJpYWJsZSIseT0idmFsdWUiLGZpbGw9ImNvbmQiLHBhbGV0dGUgPSBteXBhbCwgYWRkPSJtZWFuX3NkIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwzMCkpCnBsb3RfdmlvbF9yZXBfbm9uc2lnX3BlYWtzCmBgYAoKYGBge3J9Cmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX3Zpb2xfcmVwX2FsbC5wZGYiLHBsb3RfdmlvbF9yZXBfYWxsX3BlYWtzLHdpZHRoID0gMiwgaGVpZ2h0PSAzKQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl92aW9sX3JlcF9ES08ucGRmIixwbG90X3Zpb2xfcmVwX0RLT19wZWFrcyx3aWR0aCA9IDIsIGhlaWdodD0gMykKZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfdmlvbF9yZXBfREhYMzYucGRmIixwbG90X3Zpb2xfcmVwX0RIWDM2X3BlYWtzLHdpZHRoID0gMiwgaGVpZ2h0PSAzKQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl92aW9sX3JlcF9ub25zaWcucGRmIixwbG90X3Zpb2xfcmVwX25vbnNpZ19wZWFrcyx3aWR0aCA9IDIsIGhlaWdodD0gMykKYGBgIAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30Kc2RmIDwtIGFnZ3JlZ2F0ZSh2YWx1ZSB+IG5hbWUgKyBjb25kLCBkYXRhPW1kZiwgRlVOPSJtZWFuIikKc2RmJGNvbmQgPC0gZmFjdG9yKHNkZiRjb25kLGxldmVscz1jKCJXVCIsIkRIWDM2LS8tIiwiRkFOQ0otLy0iLCJESFgzNi0vLUZBTkNKLS8tIikpCmdndmlvbGluKHNkZiwgeD0iY29uZCIseT0idmFsdWUiLGZpbGw9ImNvbmQiLHBhbGV0dGUgPSBteXBhbFtjKDQsMSwyLDMpXSwgYWRkPSJtZWFuX3NkIikgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCw1MCkpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30Kc2RmJERIWDM2X3NpZyA8LSBzZGYkbmFtZSAlaW4lIERIWDM2X2JlZCRuYW1lCnNkZiRGQU5DSl9zaWcgPC0gc2RmJG5hbWUgJWluJSBGQU5DSl9iZWQkbmFtZQpzZGYkREtPX3NpZyA8LSBzZGYkbmFtZSAlaW4lIERLT19iZWQkbmFtZQpzZGYkREtPX3RvcCA8LSBzZGYkbmFtZSAlaW4lIERLT19iZWRfdG9wJG5hbWUKZ2d2aW9saW4oc2RmW3NkZiRESFgzNixdLCB4PSJjb25kIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsW2MoNCwxLDIsMyldLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDc1KSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpnZ3Zpb2xpbihzZGZbc2RmJEZBTkNKX3NpZyxdLCB4PSJjb25kIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsW2MoNCwxLDIsMyldLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDc1KSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpwbG90X3Zpb2xfREtPX3BlYWtzIDwtIGdndmlvbGluKHNkZltzZGYkREtPX3NpZyxdLCB4PSJjb25kIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsW2MoNCwxLDIsMyldLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDc1KSkKcGxvdF92aW9sX0RLT19wZWFrcwpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CmdndmlvbGluKHNkZltzZGYkREtPX3RvcCxdLCB4PSJjb25kIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsW2MoNCwxLDIsMyldLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDc1KSkKYGBgCiMjIyBhbm5vdGF0ZSBwZWFrIHRhYmxlCmBgYHtyfQpsaWJyYXJ5KEdlbm9taWNSYW5nZXMpCgpiZWRfcGVha3MgPC0gcmVhZC5kZWxpbShwZWFrX3VuaXZlcnNlLCBzZXA9Ilx0IiwgaGVhZGVyPUZBTFNFKQpiZWRfY2htbSA8LSByZWFkLmRlbGltKGNocm9taG1tLCBzZXA9Ilx0IiwgaGVhZGVyPUZBTFNFKQoKIyBDcmVhdGUgR2Vub21pY1JhbmdlcyBvYmplY3RzIGZvciBCRUQgZmlsZXMKZ3JBIDwtIHdpdGgoYmVkX3BlYWtzLCBHUmFuZ2VzKFYxLCBJUmFuZ2VzKFYyLCBWMywgbmFtZXMgPSBWNCkpKQpnckIgPC0gd2l0aChiZWRfY2htbSwgR1JhbmdlcyhWMSwgSVJhbmdlcyhWMiwgVjMsbmFtZXMgPSBWNCkpKQoKIyBQZXJmb3JtIGludGVyc2VjdGlvbgppbnRlcnNlY3Rpb24gPC0gZmluZE92ZXJsYXBzKGdyQSwgZ3JCKQoKZm9yIChpIGluIHNlcV9hbG9uZyhnckEpKSB7CiAgcXVlcnlfZmVhdHVyZXMgPC0gcXVlcnlIaXRzKGludGVyc2VjdGlvbilbcXVlcnlIaXRzKGludGVyc2VjdGlvbikgPT0gaV0KICBvdmVybGFwcGluZ19mZWF0dXJlcyA8LSBzdWJqZWN0SGl0cyhpbnRlcnNlY3Rpb24pW3F1ZXJ5SGl0cyhpbnRlcnNlY3Rpb24pID09IGldCiAgCiAgaWYgKGxlbmd0aChvdmVybGFwcGluZ19mZWF0dXJlcykgPiAwKSB7CiAgICBvdmVybGFwcGluZ19pbnQgPC0gcGludGVyc2VjdChnckFbcXVlcnlfZmVhdHVyZXNdLCBnckJbb3ZlcmxhcHBpbmdfZmVhdHVyZXNdKQogICAgb3ZlcmxhcHBpbmdfd2lkdGhzIDwtIHdpZHRoKG92ZXJsYXBwaW5nX2ludCkKICAgIG1heF9vdmVybGFwX2luZGV4IDwtIG92ZXJsYXBwaW5nX2ZlYXR1cmVzW3doaWNoLm1heChvdmVybGFwcGluZ193aWR0aHMpXQogICAgbWF4X292ZXJsYXBfZmVhdHVyZSA8LSBnckJbbWF4X292ZXJsYXBfaW5kZXhdCiAgICAKICAgIGJlZF9wZWFrcyRWNFtpXSA8LSBuYW1lcyhtYXhfb3ZlcmxhcF9mZWF0dXJlKQogIH0KfQoKd3JpdGUudGFibGUoYmVkX3BlYWtzLCIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfYW5ub3RhdGVkLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQoKYmVkX3BlYWtzX3RhYmxlIDwtIGNiaW5kKGJlZF9wZWFrcyxkYXRhLmZyYW1lKGJhc2VNZWFuPWxmY19ES08kYmFzZU1lYW4sREhYMzY9KGRhdGFfREhYMzYkaXNERSAmIGRhdGFfREhYMzYkbGZjPjEpLEZBTkNKPShkYXRhX0ZBTkNKJGlzREUgJiBkYXRhX0ZBTkNKJGxmYz4xKSxES089KGRhdGFfREtPJGlzREUmZGF0YV9ES08kbGZjPjEpLERIWDM2bGZjPWRhdGFfREhYMzYkbGZjLEZBTkNKbGZjPWRhdGFfRkFOQ0okbGZjLERLT2xmYz1kYXRhX0RLTyRsZmMpKQoKd3JpdGUudGFibGUoYmVkX3BlYWtzX3RhYmxlLCJHNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfYW5ub3RhdGVkLnR4dCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTJ9CiNyZWFkIGluIC0gaWYgeW91IHdhbnQgdG8gc2tpcCBkZSBub3ZvIGdlbmVyYXRpb24KYmVkX3BlYWtzX3RhYmxlIDwtIHJlYWQudGFibGUoIkc0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9hbm5vdGF0ZWQudHh0IiwgaGVhZGVyID0gVCwgc2VwID0gIlx0IikKCnZwYWw9Y29sb3JSYW1wUGFsZXR0ZShjKCJjb3JuZmxvd2VyYmx1ZSIsIm9yYW5nZSIsInJlZDIiKSkKc3RhdHMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShiZWRfcGVha3NfdGFibGUkVjQpKQpnZ2RvbnV0Y2hhcnQoc3RhdHMseCA9ICJGcmVxIixsYWJlbD0iVmFyMSIsZmlsbD12cGFsKDEwKSkKYGBgCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTN9CnZwYWw9Y29sb3JSYW1wUGFsZXR0ZShjKCJsaWdodGdyZWVuIiwiY29ybmZsb3dlcmJsdWUiLCJvcmFuZ2UiLCJyZWQyIikpCgpzdGF0cyA8LSBkYXRhLmZyYW1lKGFzLmRhdGEuZnJhbWUodGFibGUoYmVkX3BlYWtzX3RhYmxlJFY0KSksREhYMzY9YXMuZGF0YS5mcmFtZSh0YWJsZShiZWRfcGVha3NfdGFibGUkVjRbYmVkX3BlYWtzX3RhYmxlJERIWDM2PT1UUlVFXSkpWzJdLEZBTkNKPWFzLmRhdGEuZnJhbWUodGFibGUoYmVkX3BlYWtzX3RhYmxlJFY0W2JlZF9wZWFrc190YWJsZSRGQU5DSj09VFJVRV0pKVsyXSxES089YXMuZGF0YS5mcmFtZSh0YWJsZShiZWRfcGVha3NfdGFibGUkVjRbYmVkX3BlYWtzX3RhYmxlJERLTz09VFJVRV0pKVsyXSkKY29sbmFtZXMoc3RhdHMpIDwtIGMoIlN0YXRlIiwiVG90YWwiLCJESFgzNiIsIkZBTkNKIiwiREtPIikKCnN0YXRzJFRvdGFsPXN0YXRzJFRvdGFsL3N1bShzdGF0cyRUb3RhbCkqMTAwCnN0YXRzJERIWDM2PXN0YXRzJERIWDM2L3N1bShzdGF0cyRESFgzNikqMTAwCnN0YXRzJEZBTkNKPXN0YXRzJEZBTkNKL3N1bShzdGF0cyRGQU5DSikqMTAwCnN0YXRzJERLTz1zdGF0cyRES08vc3VtKHN0YXRzJERLTykqMTAwCm1kZiA8LSBtZWx0KHN0YXRzKQptZGYkU3RhdGUgPC0gZmFjdG9yKG1kZiRTdGF0ZSxsZXZlbHM9bGV2ZWxzKG1kZiRTdGF0ZSlbYygxLDMsNSw3LDQsNiwxMCw4LDksMildKQpjb2xzPWModnBhbCgxMSlbYyg0LDUsMywyLDksOCw3KV0sIiNEREREREQiLCIjRUVFRUVFIix2cGFsKDExKVsxMF0pCnBsb3RfYmFyX2Nocm9taG1tX2Fubm8gPC0gZ2diYXJwbG90KG1kZix4ID0gInZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iU3RhdGUiLHBhbGV0dGUgPWNvbHMpCnBsb3RfYmFyX2Nocm9taG1tX2Fubm8KYGBgCgoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9M30KcCA8LSBnZ2RyYXcoKSArCiAgZHJhd19wbG90KHBsb3RfYmFyX2Nocm9taG1tX2Fubm8sIHggPSAwLCB5ID0gMCwgd2lkdGggPSAuMjAsIGhlaWdodCA9IDEpICsKICBkcmF3X3Bsb3QocGxvdF92aW9sX3JlcF9ES09fcGVha3MsIHggPSAuMiwgeSA9IDAsIHdpZHRoID0gLjQwLCBoZWlnaHQgPSAwLjcpICsKICBkcmF3X3Bsb3QocGxvdF92aW9sX3JlcF9ub25zaWdfcGVha3MsIHggPSAwLjYsIHkgPSAwLCB3aWR0aCA9IC40MCwgaGVpZ2h0ID0gMC43KSArCiAgZHJhd19wbG90X2xhYmVsKGxhYmVsID0gYygiYSIsICJiIiwgImMiKSwgc2l6ZSA9IDE1LAogICAgICAgICAgICAgICAgICB4ID0gYygwLCAwLjIsIDAuNiksIHkgPSBjKDEsIDAuOCwgMC44KSkKcApnZ3NhdmUoInBhbmVscy9wZWFrX2Fubm9fdmlvbGluX3YxLnBkZiIscCx3aWR0aD04LCBoZWlnaHQ9NCkKYGBgIApgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0zfQoKcCA8LSBnZ2RyYXcoKSArCiAgZHJhd19wbG90KHBsb3RfYmFyX2Nocm9taG1tX2Fubm8sIHggPSAwLCB5ID0gMCwgd2lkdGggPSAuNCwgaGVpZ2h0ID0gMSkgKwogIGRyYXdfcGxvdChwbG90X3Zpb2xfcmVwX0RLT19wZWFrcywgeCA9IC40LCB5ID0gMC41LCB3aWR0aCA9IC42MCwgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90KHBsb3RfdmlvbF9yZXBfbm9uc2lnX3BlYWtzLCB4ID0gMC40LCB5ID0gMCwgd2lkdGggPSAuNjAsIGhlaWdodCA9IDAuNSkgKwogIGRyYXdfcGxvdF9sYWJlbChsYWJlbCA9IGMoImEiLCAiYiIsICJjIiksIHNpemUgPSAxNSwKICAgICAgICAgICAgICAgICAgeCA9IGMoMCwgMC40LCAwLjQpLCB5ID0gYygxLCAxLCAwLjUpKQpwCmdnc2F2ZSgicGFuZWxzL3BlYWtfYW5ub192aW9saW5fdjIucGRmIixwLHdpZHRoPTgsIGhlaWdodD0zKQpgYGAgCg==